/*******************************************************************************
 * Copyright (C) 2014 The Calrissian Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package org.calrissian.restdoclet.example.spring;

import static org.springframework.web.bind.annotation.RequestMethod.POST;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

/**
 * Example implementation of a REST endpoints using spring to highlight documentation features.
 *
 * @name example
 */
@RestController
@RequestMapping(value = { "/api/foo", "/bar" })
public class ExampleController {

    /**
     * Stores the color for a particular user
     *
     * @param file
     *            The color value to store for the user
     */
    @RequestMapping(value = "/file", method = RequestMethod.POST)
    public List<ResponseBodyObj> setColor(@RequestParam MultipartFile file) {
        return null;
    }

    /**
     * Stores the color for a particular user
     *
     * @param value
     *            The color value to store for the user
     */
    @RequestMapping(value = "/user/color")
    public ResponseBodyObj search(@Validated RequestBodyObj value) {
        ResponseBodyObj responseBodyObj = new ResponseBodyObj();
        responseBodyObj.setValue1(value.value1);
        responseBodyObj.setValue2(value.value2);
        ResponseBodyObj.ResponseBodyObjInner inner = new ResponseBodyObj.ResponseBodyObjInner();
        inner.setValue1(value.inner.value1);
        inner.setValue2(value.inner.value2);
        responseBodyObj.setInner(inner);
        return responseBodyObj;
    }

    /**
     * Stores the color for a particular user
     *
     * @param userId
     *            User id of the user.
     * @param normalize
     *            Determines whether the result will be standardized
     * @param value
     *            The color value to store for the user
     */
    @RequestMapping(value = "/user/{name}/color", method = RequestMethod.POST)
    public List<ResponseBodyObj> setColor(@PathVariable("name") String userId,
                                          @RequestParam(required = false) boolean normalize,
                                          @RequestBody RequestBodyObj value) {
        userColors.put(userId, value.value1);
        return null;
    }

    /**
     * This class provides 3 example endpoints descriptions with a mix of annotations and javadoc overloads.
     *
     * The top level request mapping defines to path values that means that the amount of documented
     * endpoints will double. For example the endpoint defined by the "/add" endpoint will actually be
     * listed as both "/foo/add" and "/bar/add". The same is true for when there are multiple HTTP methods.
     * defined.
     *
     * With Spring if no method is defined, then the documentation will default to a GET method.
     *
     */

    private static int                 count      = 0;
    private static Map<String, String> userColors = new HashMap<String, String>();

    /**
     * Simply adds the value provided via the query parameter to a running total.
     *
     * @param value
     *            Value to be added to a running total.
     * @return The current total.
     */
    @RequestMapping(value = "/add", method = POST)
    public String postExample(@RequestParam int value) {
        count += value;
        return Integer.toString(count);
    }

    /**
     * Retrieves the stored color for a particular user.
     *
     * @param userId
     *            user id of the user.
     * @param normalize
     *            Determines whether the result will be standardized
     * @pathVar name Name of the user to retrieve the color for
     * @queryParam normalize If set to "true" the name of the color will be normalized before being returned.
     */
    @RequestMapping(value = "/user/{name}/color")
    public FacadeInvokeDataResult<List<ResponseBodyObj>> getColor(@PathVariable("name") String userId,
                                                                  @RequestParam(required = false) boolean normalize) {
        // if (!userColors.containsKey(userId))
        // return "";

        // return (normalize ? userColors.get(userId).toLowerCase() : userColors.get(userId));
        return null;
    }

    // /**
    // * Stores the color for a particular user
    // *
    // * @param userId User id of the user.
    // * @param value The color value to store for the user
    // * @pathVar name Name of the user to store the color for
    // * @queryParam color The color to give to the user
    // */
    // @RequestMapping(value = "/user/{name}/color", method = { POST,
    // PUT }, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.TEXT_PLAIN_VALUE)
    // @ResponseBody
    // public String setColor(@PathVariable("name") String userId, @RequestBody String value) {
    // userColors.put(userId, value);
    // return getColor(userId, false);
    // }

    public static class BaseResponseBodyObj {
        /**
         * value01 desc
         */
        private String value01;
        /**
         * value02 desc
         */
        private String value02;

        public String getValue01() {
            return value01;
        }

        public void setValue01(String value01) {
            this.value01 = value01;
        }

        public String getValue02() {
            return value02;
        }

        public void setValue02(String value02) {
            this.value02 = value02;
        }
    }

    public static class ResponseBodyObj extends BaseResponseBodyObj {
        /**
         * value1 desc
         */
        private String               value1;
        /**
         * value2 desc
         */
        private String               value2;

        private ResponseBodyObjInner inner;

        public String getValue1() {
            return value1;
        }

        public void setValue1(String value1) {
            this.value1 = value1;
        }

        public String getValue2() {
            return value2;
        }

        public void setValue2(String value2) {
            this.value2 = value2;
        }

        public ResponseBodyObjInner getInner() {
            return inner;
        }

        public void setInner(ResponseBodyObjInner inner) {
            this.inner = inner;
        }

        public static class ResponseBodyObjInner {
            /**
             * value1 desc
             */
            private String value1;
            /**
             * value2 desc
             */
            private String value2;

            public String getValue1() {
                return value1;
            }

            public void setValue1(String value1) {
                this.value1 = value1;
            }

            public String getValue2() {
                return value2;
            }

            public void setValue2(String value2) {
                this.value2 = value2;
            }

        }

    }

    public static class RequestBodyObj {
        /**
         * value1 desc
         */
        private String              value1;
        /**
         * value2 desc
         */
        private String              value2;

        /**
         * value3 desc
         */
        private TestEnum            value3;
        /**
         * value4 desc
         */
        private int                 value4;

        /**
         * inner
         */
        private RequestBodyObjInner inner;

        public String getValue1() {
            return value1;
        }

        public void setValue1(String value1) {
            this.value1 = value1;
        }

        public String getValue2() {
            return value2;
        }

        public void setValue2(String value2) {
            this.value2 = value2;
        }

        /**
         * Getter method for property <tt>value4</tt>.
         *
         * @return property value of value4
         */
        public int getValue4() {
            return value4;
        }

        /**
         * Setter method for property <tt>value4</tt>.
         *
         * @param value4
         *            value to be assigned to property value4
         */
        public void setValue4(int value4) {
            this.value4 = value4;
        }

        public RequestBodyObjInner getInner() {
            return inner;
        }

        public void setInner(RequestBodyObjInner inner) {
            this.inner = inner;
        }

        public static class RequestBodyObjInner {
            /**
             * value1 desc
             */
            private String value1;
            /**
             * value2 desc
             */
            private String value2;

            public String getValue1() {
                return value1;
            }

            public void setValue1(String value1) {
                this.value1 = value1;
            }

            public String getValue2() {
                return value2;
            }

            public void setValue2(String value2) {
                this.value2 = value2;
            }

        }

        public static enum TestEnum {
                                     TEST1, TEST2
        }
    }

}
